package com.fabrizio.dissociator;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;

import android.app.Activity;
import android.os.Bundle;
import android.text.Editable;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.ViewFlipper;

public class Dissociator extends Activity {
    /** Called when the activity is first created. */
    ViewFlipper flipper; 
    EditText input;
    TextView output;
    public static final int MAXOUTPUTLEN = 20;
    public static final int PREFIXLEN = 2;
    public static final String DISSOCBLANK = "DISSOCBLANK";
    
    @Override 
    public void onCreate(Bundle icicle) { 
        super.onCreate(icicle); 
        setContentView(R.layout.main); 
 
        flipper=(ViewFlipper)findViewById(R.id.details); 
        input = (EditText)findViewById(R.id.input);
        output = (TextView)findViewById(R.id.output);
        Button btn=(Button)findViewById(R.id.flip_me); 
 
        btn.setOnClickListener(new View.OnClickListener() { 
            public void onClick(View view) {
            String dissOut = dissociate(input.getText());
            output.setText(dissOut);
            flipper.showNext(); 
            } 
        }); 
    } 
    
    private String dissociate(Editable corpus){
		ArrayList<String> suffixes;
    	int i;
    	
    	String corpusStr = corpus.toString();
    	String[] corpusStrArray = corpusStr.split("\\s");
    	Log.d("Test string is:", corpusStr);
    	ArrayList<String> corpusStrListArray = new ArrayList<String>(Arrays.asList(corpusStrArray)); 

    	// Insert place holder words to simplify
    	// flow control and handling of boundary cases.
    	// Need n place-holders at start, and one at end.
    	corpusStrListArray.add(corpusStrListArray.size(), DISSOCBLANK);
    	i = 0;
    	while(i < PREFIXLEN){
    	    corpusStrListArray.add(0, DISSOCBLANK);
    	    i++;
    	}
    	
    	ArrayList<KGram> frequencyTable = new ArrayList<KGram>();    	
    	
    	// Create the frequency table.
    	i = 0;
    	do {
    	//for (i = 0; i < MAXOUTPUTLEN; i++){
    		ArrayList<String> prefix = getCurrPrefix(corpusStrArray, i);	
    		//ArrayList<String> prefix = getCurrPrefix((String[])corpusStrListArray.toArray(), i);
    		KGram kgram = new KGram(prefix.toArray(new String[prefix.size()]));    
    		//KGram kgram = new KGram((String[])prefix.toArray());    		
            // Suffix occurs one word after the last word in the prefix, 
    		// hence index of last word in prefix plus one.

    		suffixes = getSuffixesForPrefix(corpusStrListArray, prefix);    		
            Iterator<String> it = suffixes.iterator();
            
            while(it.hasNext()){
                kgram.addSuffix(it.next());
            }
            
    		frequencyTable.add(kgram);	
    		i++;
    	//}
    	} while(!suffixes.contains(DISSOCBLANK));
    	
    	// Generate the text from the frequency table.    	
    	ArrayList<String> generatedStrArray = new ArrayList<String>();
    	for(i = 0; i <= frequencyTable.size() - 1; i++) {
    		generatedStrArray.add(frequencyTable.get(i).generateNextWord());
    		// add a space between each word.
    		generatedStrArray.add(" ");
    	}
    	return generatedStrArray.toString();
    }
    
    private ArrayList<String> getSuffixesForPrefix(ArrayList<String> corpus, ArrayList<String> prefix){
    	int currSuffixIdx, prefixStartFoundAt, prefixEndFoundAt;
    	ArrayList<String> suffixes = new ArrayList<String>();
    	ArrayList<String> corpusCpy = new ArrayList<String>(corpus);
    	String nextPrefixOccurenceCandidate = null;
    	
    	do {
    	    prefixStartFoundAt = corpusCpy.indexOf(prefix.toArray()[0]);
    	    prefixEndFoundAt = corpusCpy.indexOf(prefix.toArray()[PREFIXLEN - 1]);    
    	
    	    if (prefixStartFoundAt >= 0 && prefixEndFoundAt >= 0){    	    	
        	    // If the last word in the prefix string occurs in the corpus 
        	    // before the first word in the prefix, then we adjust the 
        	    // prefix end to guess that it occurs at prefix start + PREFIXLEN - 1
    	    	
        	    if(prefixStartFoundAt > prefixEndFoundAt){
        	    	prefixEndFoundAt = prefixStartFoundAt + PREFIXLEN - 1;
        	    }
        	    
    	        nextPrefixOccurenceCandidate =  corpusCpy.subList(prefixStartFoundAt, prefixEndFoundAt + 1).toString();
    	        Log.d("nextPrefixOccurenceCandidate is", nextPrefixOccurenceCandidate);
    	        Log.d("prefix is", prefix.toString());

		// convert to arraylist for convenience                 
		String[] candidateStrArray = nextPrefixOccurenceCandidate.toString().split("\\s");
		ArrayList<String> prefixCandidate = new ArrayList<String>(Arrays.asList(candidateStrArray));

		int j = prefixEndFoundAt - prefixStartFoundAt + 1;
		int i = 0;
		while(j > PREFIXLEN){

		    if(prefix.toString().equals(prefixCandidate.toString())){
		            nextPrefixOccurenceCandidate = prefixCandidate.toString();
		    }
		    j--;
		    i++;
		    prefixCandidate.subList(0, 1).clear();
		}  
		    	          
    	        if (prefix.toString().equals(nextPrefixOccurenceCandidate)){
    		        // append the next suffix to the suffixes ArrayList
    		        // truncate the corpus from its beginning up to the current suffix
    	        	// thus shortening to corpus
    	            currSuffixIdx = corpusCpy.indexOf(prefix.toArray()[PREFIXLEN - 1]) + 1;
    	            suffixes.add((String)corpusCpy.toArray()[currSuffixIdx]);
    	            corpusCpy.subList(0, currSuffixIdx).clear();
    	        } else {
    	        	corpusCpy.subList(0, prefixEndFoundAt + 1).clear();
    		        nextPrefixOccurenceCandidate = "temp";
    	        }
    	    } else {
    	    	nextPrefixOccurenceCandidate = null;
    	    }

    	} while (nextPrefixOccurenceCandidate != null);
    	
    	return suffixes;
    }
    
    private ArrayList<String> getCurrPrefix(String[] corpus, int position){
    	int i;
    	ArrayList<String> prefix = new ArrayList<String>();

    	for(i = 0; i < PREFIXLEN; i++){
    		prefix.add(corpus[i + position]);
    	}
    	
    	return prefix;
    }
}

